/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controller.Capacidades;

import Entity.DatosCapacidades;
import Entity.Operacion;
import java.util.ArrayList;

/**
 *
 * @author camilourd
 */
public class MetodosCapacidades {
    private DatosCapacidades dc;

    public MetodosCapacidades() {
        dc = new DatosCapacidades();
    }
    
    public void addOperacion(String name, ArrayList<Double> prods, double mqDisp, double diasHab, double numTrabsMaq, double numTrabsDisps, double horasMantenimiento, double INRs, double perdidasOperacionales, double factorUtilizacion) {
        ArrayList<Double> copia = (ArrayList<Double>) prods.clone();
        dc.getOperaciones().add(new Operacion(name, copia, mqDisp, diasHab, numTrabsMaq, numTrabsDisps, horasMantenimiento, INRs, perdidasOperacionales, factorUtilizacion));
    }
    
    public void addNumTurnos(double numTurnos) {
        dc.setNumTurnos(numTurnos);
    }
    
    public void addDuracionTurnos(double horas, double minutos) {
        double duracionTurnos = horas + (minutos / 60.0);
        dc.setDuracionTurnos(duracionTurnos);
    }
    
    public void addIncapacidadLaboral(double incapacidadLaboral) {
        dc.setIncapacidadLaboral(incapacidadLaboral);
    }
    
    public void addParadasPlanta(double paradasPlanta) {
        dc.setParadasPlanta(paradasPlanta);
    }
    
    public void addActividadesLudicasCulturales(double actividadesLudicasCulturales) {
        dc.setActividadesLudicasCulturales(actividadesLudicasCulturales);
    }
    
    public void addHorizontePlaneacion(double horizontePlaneacion) {
        dc.setHorizontePlaneacion(horizontePlaneacion);
    }
    
    public void addTiempoPreparacion(double tiempoPreparacion) {
        dc.getTiempoPreparacion().add(tiempoPreparacion);
    }
    
    public void addTamLote(double tamLote) {
        dc.getTamLote().add(tamLote);
    }
    
    public void addDemandaInicial(double demIni) {
        dc.getDemandaInicial().add(demIni);
    }
    
    public void addInventarioInicial(double invIni) {
        dc.getInventarioInicial().add(invIni);
    }
    
    public double calcularNumeroMaquinas(double data) {
        if(data <= 0.001) return 0.0;
        else if(data < 1) return 1.0;
        else if(data < (Math.ceil(data) - 0.1)) return Math.floor(data);
        else return Math.ceil(data);
    }
    
    public boolean comprobarInventarioDemanda() {
        int n = dc.getDemandaInicial().size();
        boolean ok = true;
        
        for(int i = 0;i < n; ++i) {
            ok &= (dc.getDemandaInicial().get(i) < dc.getInventarioInicial().get(i));
        }
        return ok;
    }
    
    public void calcular(javax.swing.JTable table) {
        int n = dc.getDemandaInicial().size();
        int m = dc.getOperaciones().size();
        
        if(m > 0) {
            // Obtener datos
            ArrayList<Operacion> opers = dc.getOperaciones();
            ArrayList<Double> demIni = dc.getDemandaInicial();
            ArrayList<Double> invIni = dc.getInventarioInicial();
            ArrayList<Double> tamLote = dc.getTamLote();
            ArrayList<Double> tiempoPrep = dc.getTiempoPreparacion();
            
            // Hallar Np para cada producto
            ArrayList<Double> Np = new ArrayList<Double>();
            
            for(int i = 0;i < n; ++i) {
                Np.add(Math.ceil((demIni.get(i) - invIni.get(i)) / tamLote.get(i)));
            }
            
            // hallar Kn para cada operación
            ArrayList<Double> Kn = new ArrayList<Double>();
            double inr;
            
            for(int i = 0;i < m; ++i) {
                Kn.add(0.0);
                for(int j = 0;j < n; ++j) {
                    if(opers.get(i).getProductos().get(j) > 0.0) {
                        Kn.set(i, Kn.get(i) + (Np.get(j) * (tiempoPrep.get(j) + (opers.get(i).getProductos().get(j) / 3600.0 * tamLote.get(j)))));
                    }
                }
                inr = opers.get(i).getINRs();
                Kn.set(i, Kn.get(i) * (1.0 - (inr / 100.0)));
                if(Kn.get(i) < 0.0) Kn.set(i, 0.0);
            }
            
            // Hallar Cd por máquina de proceso
            ArrayList<Double> Cdmaq = new ArrayList<Double>();
            ArrayList<Double> Nmp = new ArrayList<Double>();
            ArrayList<Double> Ntp = new ArrayList<Double>();
            Operacion op;
            double data, mqt = 0.0;
            
            if(!comprobarInventarioDemanda()) {
                for(int i = 0;i < m; ++i) {
                    op = opers.get(i);
                    Cdmaq.add((op.getDiasHabiles() * dc.getNumTurnos() * dc.getDuracionTurnos()) - (op.getPerdidasOperacionales() * dc.getHorizontePlaneacion()));
                    Nmp.add(Math.min(calcularNumeroMaquinas(Kn.get(i) / Cdmaq.get(i)), op.getMaquinasDisponibles()));

                    if(op.getNumeroTrabajadoresMaquina() > 0.0){
                        data = Math.min(Nmp.get(i) * op.getNumeroTrabajadoresMaquina(), op.getNumeroTrabajadoresDisponibles());
                        Nmp.set(i, data / op.getNumeroTrabajadoresMaquina());
                    }
                    Ntp.add(Nmp.get(i) * op.getNumeroTrabajadoresMaquina());
                    mqt += op.getMaquinasDisponibles();
                }
            } else {
                for(int i = 0;i < m; ++i) {
                    op = opers.get(i);
                    Cdmaq.add((op.getDiasHabiles() * dc.getNumTurnos() * dc.getDuracionTurnos()) - (op.getPerdidasOperacionales() * dc.getHorizontePlaneacion()));
                    
                    Nmp.add(0.0);
                    Ntp.add(0.0);
                    mqt += op.getMaquinasDisponibles();
                }
            }
            
            // Devolver resultados para un turno
            for(int i = 0;i < m; ++i) {
                op = opers.get(i);
                table.setValueAt(op.getOperacion(), i, 0);
                table.setValueAt(op.getMaquinasDisponibles(), i, 1);
                table.setValueAt(Nmp.get(i), i, 2);
                table.setValueAt(op.getMaquinasDisponibles() - Nmp.get(i), i, 3);
                table.setValueAt(op.getNumeroTrabajadoresDisponibles(), i, 4);
                table.setValueAt(Ntp.get(i), i, 5);
                table.setValueAt(op.getNumeroTrabajadoresDisponibles() - Ntp.get(i), i, 6);
            }
            
             // Capacidad disponible por proceso
            ArrayList<Double> G1 = new ArrayList<Double>();
            ArrayList<Double> cdp = new ArrayList<Double>();
            double sumcdt = 0.0;
            
            for(int i = 0;i < m; ++i){
                op = opers.get(i);
                G1.add(Nmp.get(i) * op.getHorasMantenimiento() * dc.getHorizontePlaneacion());
                cdp.add(((Nmp.get(i) * op.getDiasHabiles() * dc.getNumTurnos() * dc.getDuracionTurnos()) - ((G1.get(i) + ((dc.getIncapacidadLaboral() + dc.getActividadesLudicasCulturales() + dc.getParadasPlanta()) / mqt)) * Nmp.get(i))) * (op.getFactorUtilizacion() / 100.0));
                sumcdt += cdp.get(i);
            }
            
            // Calculo capacidades
            dc.setCapacidadTeorica(mqt * 365 * 24);
            dc.setCapacidadDisponibleSistema(sumcdt);
            
            ArrayList<Double> tsu = new ArrayList<Double>();
            double sumto, cr = 0.0;
            
            for(int i = 0;i < n; ++i) {
                sumto = 0.0;
                for(int j = 0;j < m; ++j) sumto += dc.getOperaciones().get(j).getProductos().get(i);
                tsu.add((dc.getTiempoPreparacion().get(i) / dc.getTamLote().get(i)) + (sumto / 3600));
                cr += tsu.get(i) * (dc.getDemandaInicial().get(i) - dc.getInventarioInicial().get(i));
            }
            dc.setCapacidadRequerida(cr);
            
            double sumG1a = 0.0;
            for(int i = 0;i < m; ++i) {
                op = opers.get(i);
                sumG1a += op.getMaquinasDisponibles() * op.getHorasMantenimiento() * dc.getHorizontePlaneacion();
            }
            dc.setCapacidadInstalada(dc.getCapacidadTeorica() - sumG1a);
            
            dc.setFactorUtilizacionSistema(dc.getCapacidadRequerida() / dc.getCapacidadDisponibleSistema() * 100);
            dc.setFactorCapacidadInstalada(dc.getCapacidadRequerida() / dc.getCapacidadInstalada() * 100);
        }
    }
    
    public ArrayList<Double> obtenerCapacidades() {
        ArrayList<Double> caps = new ArrayList<Double>();
        
        caps.add(dc.getCapacidadTeorica());
        caps.add(dc.getCapacidadDisponibleSistema());
        caps.add(dc.getCapacidadRequerida());
        caps.add(dc.getCapacidadInstalada());
        caps.add(dc.getFactorUtilizacionSistema());
        caps.add(dc.getFactorCapacidadInstalada());
        
        return caps;
    }
    
    public String aproxDouble(double data) {
        return String.format("%.3f", data);
    }
}
